<template>
  <img
    class="tpv-audio_icon"
    :class="{
      'tpv-audio_icon-paused': !playing,
      'tpv-audio_icon-playing': rotate,
      'tpv-audio_icon-toggle': !rotate,
    }"
    :src="audioIcon"
    @click="handleToggleAudio"
    alt="" />
</template>

<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator'

import AudioPlayer, {
  AudioEmitType,
  autoTriggerWithoutUIInteraction,
} from './player'
import AudioOnIcon from './img/audio-on.png'
import AudioOffIcon from './img/audio-off.png'
import AudioRotate from './img/audio-rotate.png'

/**
 * 简易音频播放器
 *
 * 使用方式
 * <TpvAudio :src="arrayBuffer" autoplay loop cover="xxx.png" rotate />
 *
 * cover: 音频播放器图标
 * rotate: 播放时，是否旋转播放器图标，若为 false，则使用默认的播放和暂停图标，不使用 cover
 *
 */
@Component({})
export default class TpvAudio extends Vue {
  // 音频地址
  // @Prop({ type: [String, ArrayBuffer] }) src!: string | ArrayBuffer
  // 是否自动播放
  // @Prop({ type: Boolean }) autoplay!: boolean
  // 是否循环播放
  // @Prop({ type: Boolean }) loop!: boolean
  // 音乐图标
  // @Prop({ type: String }) cover!: string
  // 音乐图标是否旋转
  // @Prop({ type: Boolean, default: false }) rotate!: boolean
  src = `${process.env.VUE_APP_ASSET}media/dft.mp3`
  loop = true
  rotate = true
  autoplay = true
  cover = ''
  player = new AudioPlayer()

  // 播放器是否播放成功过
  played = false

  // 播放器播放状态
  playing = false

  // 用户点击操作的播放状态，false 表示用户关闭了，true 表示用户打开了
  userPlaying = false

  get audioIcon() {
    return this.rotate
      ? this.cover || AudioRotate
      : this.playing
      ? AudioOnIcon
      : AudioOffIcon
  }

  async beforeDestroy() {
    document.removeEventListener('visibilitychange', this.visibilitychange)
    await this.player.stop()
    this.playing = false
    this.userPlaying = false
    this.played = false
  }
  mounted() {
    document.addEventListener('visibilitychange', this.visibilitychange)
    if (this.autoplay) {
      let startingAudio = false
      autoTriggerWithoutUIInteraction(
        async (stopTry: () => void, emitType: AudioEmitType, tip?: string) => {
          if (this.played) {
            console.info('曾播放成功过，无需再自动播放！')
            return
          }

          if (startingAudio) {
            if (
              emitType !== AudioEmitType.UserClick &&
              emitType !== AudioEmitType.WxNetworkEvent
            ) {
              console.info('已尝试播放，非用户操作，不做处理！')
              return
            }

            // FIX iOS 微信环境下，需要在 getNetworkType 事件或用户点击触发时，resume 播放，才会实际播放
            console.info('开始 resume 来触发', tip)
            await this.player.resume()
            console.info('resume 触发播放成功')
            this.playing = true
            this.played = true
            startingAudio = false
            return
          }

          console.info(
            '尝试播放，当前是否播放:',
            this.playing,
            '触发类型:',
            emitType,
          )
          startingAudio = true
          await this.player.play(this.src, this.loop)
          console.info('尝试播放成功', tip)
          this.played = true
          this.playing = true
          this.userPlaying = true
          stopTry()
          startingAudio = false
        },
      )
    }
  }
  async visibilitychange() {
    if (document.hidden) {
      await this.player.stop()
      this.playing = false
      // 这里不能改变 usePlaying 状态，非用户主动关停

      return
    }

    if ((this.played || this.autoplay) && this.userPlaying) {
      await this.player.resume()
      console.info('切回页面播放成功')
      this.playing = true
    }
  }
  async handleToggleAudio() {
    // 未开始播放
    if (!this.player.mp3) {
      console.info('没有 mp3 尝试播放')
      await this.player.play(this.src, this.loop)
      this.playing = true
      this.userPlaying = true

      return
    }

    if (this.player.state === 'running') {
      console.info('暂停播放')
      await this.player.stop()
      this.playing = false
      this.userPlaying = false

      return
    }

    console.info('恢复播放')
    await this.player.resume()
    this.playing = true
    this.userPlaying = true
  }
}
</script>
<style lang="scss">
@keyframes music-cd {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}

.tpv-audio {
  &_icon {
    display: block;
    width: 100%;
    height: 100%;
    line-height: 0;
    overflow: hidden;

    &-toggle {
      width: 20px;
      height: 25px;
      position: fixed;
      right: 0;
      top: 20px;
    }

    &-playing {
      animation: music-cd 5s linear 0s infinite;
    }

    &-paused {
      animation-play-state: paused;
    }
  }
}
</style>
